// utils/path.utils.ts
import { dirname, join, normalize, sep } from "node:path";

/**
 * @class PathUtils
 * @description 提供安全、跨平台的路径操作工具方法，避免直接使用魔法字符串 '/' 或 '\\'
 * 支持文件系统路径（FS）和 URL/API 路径（URL）两类场景。
 *
 * @example
 * // 文件路径（自动适配操作系统）
 * PathUtils.joinFs('uploads', 'avatars', 'user.png'); // Windows: 'uploads\\avatars\\user.png'
 *
 * // URL 路径（始终使用 '/'，标准化输出）
 * PathUtils.joinUrl('api', 'v1', 'users'); // → 'api/v1/users'
 *
 * // 清理多余斜杠
 * PathUtils.normalizeUrl('///api//v1///users//'); // → '/api/v1/users/'
 */
export class PathUtils {
    /**
     * 文件系统路径分隔符（平台相关）
     * - Windows: `\`
     * - Linux/macOS: `/`
     */
    static readonly FS_SEP = sep;

    /**
     * URL/API 路径分隔符（标准正斜杠，平台无关）
     */
    static readonly URL_SEP = "/";

    /**
     * 拼接文件系统路径，自动使用当前操作系统的路径分隔符
     * @param parts - 路径片段数组
     * @returns 拼接后的文件系统路径
     * @example
     * PathUtils.joinFs('src', 'assets', 'logo.png') // → 'src/assets/logo.png' (Unix) 或 'src\\assets\\logo.png' (Windows)
     */
    static joinFs(...parts: string[]): string {
        return normalize(join(...parts));
    }

    /**
     * 拼接 URL 或 API 路径，始终使用正斜杠 `/`，并自动合并多余斜杠
     * 不会自动添加或删除首尾斜杠，保留原始语义
     * @param parts - 路径片段数组
     * @returns 标准化后的 URL 路径
     * @example
     * PathUtils.joinUrl('api', 'v1', 'users') // → 'api/v1/users'
     * PathUtils.joinUrl('/api/', '//v1//', 'users/') // → '/api/v1/users/'
     */
    static joinUrl(...parts: string[]): string {
        if (parts.length === 0) return "";
        return this.normalizeUrl(parts.join(this.URL_SEP));
    }

    /**
     * 将 src 目录以下的目录名作为 controller path 返回
     * @param {string} uri - 必传 __dirname
     * @returns {string}
     * @example
     * "nestjs-project/src/modules/user/user.controller.ts" => "modules/user"
     */
    static dirnameAsPath(uri: string): string {
        try {
            const dirPath = dirname(normalize(uri)); // 获取目录，排除文件名
            const parts = dirPath.split(sep);
            const index = parts.findIndex(part => part.toLowerCase() === "src"); // 不区分大小写
            if (index === -1) return "";
            return parts
                .slice(index + 1)
                .filter(p => p.length > 0)
                .join(this.URL_SEP); // 过滤空
        } catch (error) {
            console.error("Error processing directory path:", error);
            return "";
        }
    }

    /**
     * 标准化 URL 路径：去除首尾空格，合并中间多余斜杠，可选是否保留首尾斜杠
     * @tip 标准化文件系统路径可使用 Node.js 的 `path.normalize` 方法
     * @param pathStr - 原始路径字符串
     * @param options - 配置选项
     * @param options.leadingSlash - 是否强制保留开头斜杠（默认：保持原样）
     * @param options.trailingSlash - 是否强制保留结尾斜杠（默认：保持原样）
     * @returns 标准化后的路径
     * @example
     * PathUtils.normalizeUrl('  ///api//v1/users//  ') // → '/api/v1/users/'
     * PathUtils.normalizeUrl('api/v1/users', { leadingSlash: true }) // → '/api/v1/users'
     */
    static normalizeUrl(
        pathStr: string,
        options: {
            leadingSlash?: boolean;
            trailingSlash?: boolean;
        } = {}
    ): string {
        let result = (pathStr || "").trim().replace(/\/+/g, "/");

        // 处理开头斜杠
        if (options.leadingSlash === true && !result.startsWith("/")) {
            result = "/" + result;
        } else if (options.leadingSlash === false && result.startsWith("/")) {
            result = result.slice(1);
        }

        // 处理结尾斜杠
        if (options.trailingSlash === true && !result.endsWith("/")) {
            result = result + "/";
        } else if (options.trailingSlash === false && result.endsWith("/")) {
            result = result.slice(0, -1);
        }

        return result;
    }

    /**
     * 移除路径开头的斜杠（如果存在）
     * @param pathStr - 输入路径
     * @returns 移除开头斜杠后的路径
     * @example
     * PathUtils.trimLeadingSlash('/api/v1') // → 'api/v1'
     */
    static trimLeadingSlash(pathStr: string): string {
        return pathStr.replace(/^\/+/, "");
    }

    /**
     * 移除路径结尾的斜杠（如果存在）
     * @param pathStr - 输入路径
     * @returns 移除结尾斜杠后的路径
     * @example
     * PathUtils.trimTrailingSlash('api/v1/') // → 'api/v1'
     */
    static trimTrailingSlash(pathStr: string): string {
        return pathStr.replace(/\/+$/, "");
    }

    /**
     * 同时移除路径首尾斜杠
     * @param pathStr - 输入路径
     * @returns 首尾无斜杠的路径
     * @example
     * PathUtils.trimSlashes('/api/v1/') // → 'api/v1'
     */
    static trimSlashes(pathStr: string): string {
        return this.trimTrailingSlash(this.trimLeadingSlash(pathStr));
    }

    /**
     * 确保路径以斜杠开头
     * @param pathStr - 输入路径
     * @returns 以斜杠开头的路径
     * @example
     * PathUtils.ensureLeadingSlash('api/v1') // → '/api/v1'
     */
    static ensureLeadingSlash(pathStr: string): string {
        return pathStr.startsWith("/") ? pathStr : "/" + pathStr;
    }

    /**
     * 确保路径以斜杠结尾
     * @param pathStr - 输入路径
     * @returns 以斜杠结尾的路径
     * @example
     * PathUtils.ensureTrailingSlash('api/v1') // → 'api/v1/'
     */
    static ensureTrailingSlash(pathStr: string): string {
        return pathStr.endsWith("/") ? pathStr : pathStr + "/";
    }
}
